package com.yanfei.zero.apis;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.yanfei.zero.application.handler.secret.IgnoreDecrypt;
import com.yanfei.zero.domain.user.model.User1;
import com.yanfei.zero.domain.user.repository.User1Repository;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
/**
 * 多线程事务
 */
@RestController
@Tag(name="多线程事务")
@Slf4j
public class MultiThreadTransactionController {
	
	@Resource
	private PlatformTransactionManager transactionManager;
	
	@Resource
	private User1Repository user1Repository;
	
	
	@Operation(summary = "多线程")
    @PostMapping(value="/multiThread")
	// @AddLock("lock:121")
//    @AddLog
	@IgnoreDecrypt
	@CrossOrigin(originPatterns = "*", methods = {RequestMethod.POST})
	Object  Optimize1(@RequestBody User1 user1) {
		
		 BlockingQueue<TransactionStatus>  transactionStatuses = new LinkedBlockingQueue<>();
		 AtomicBoolean isCommit = new AtomicBoolean(true);
		 DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别，开启新事务，这样会比较安全些。
		 TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
		
		 try {
			 user1Repository.save(user1);
			 
		} catch (Exception e) {
			log.error("主线程执行失败,回滚事务"+Thread.currentThread().getName());
			transactionManager.rollback(status);
			isCommit.set(false);
			throw new RuntimeException("主线程执行失败");
		}
	
		 
        CompletableFuture<Integer>[] futures = new CompletableFuture[5];
        // 使用for循环创建并启动多个CompletableFuture任务
        for (int i = 0; i < 5; i++) {
        	
            int taskNumber = i + 1;
            final CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                // 模拟一个耗时的任务，返回任务编号
             DefaultTransactionDefinition def1 = new DefaultTransactionDefinition();
       		 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别，开启新事务，这样会比较安全些。
       		 TransactionStatus status1 = transactionManager.getTransaction(def1); // 获得事务状态
            	try {
            		if(taskNumber==5) {
                		Assert.isTrue(false, "test");
                	}
            		User1 use2 = new User1();
                	use2.setPassword(user1.getPassword());
                	use2.setEmail(user1.getEmail());
                	use2.setName("task"+taskNumber);
              		user1Repository.save(use2);
                	System.out.println("Task " + taskNumber + " completed");
                	transactionStatuses.add(status1);
                	
				} catch (Exception e) {
					isCommit.set(false);
					log.error("子任务执行失败,回滚事务"+Thread.currentThread().getName());
					transactionManager.rollback(status1);
					 //其他任务还没执行的不需要执行了
					for (CompletableFuture<Integer> completableFuture : futures) {
						completableFuture.cancel(true);
					}
				}
				
                return taskNumber;
            });
            futures[i] = future;
        }
        // 注册异步回调函数以处理所有CompletableFuture的结果
        CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(futures);
        // 等待回调函数执行完成，我们就可以确保在主线程执行完之前，回调函数能够执行完。
        allOfFuture.join();
        if (!transactionStatuses.isEmpty()&&isCommit.get()) {
            transactionStatuses.forEach(s -> transactionManager.commit(s));
        }else {
        	transactionStatuses.forEach(s -> transactionManager.rollback(s));
        }
        System.out.println("完成任务");
        transactionManager.commit(status);
        
		return true;
    }
	
	
	
}
